Consul快速入门(三):Spring Cloud Consul服务注册与发现

1、前言

本文通过创建provider-service、consumer-service两个微服务,并通过feign接口调用来演示Spring Cloud整合Consul。阅读本文需要前置知识:

  • Spring Boot
  • Spring Cloud
  • Spring Cloud Feign

2、搭建provider-service服务

2.1、创建maven模块

创建provider项目,添加provider-service、provider-service-remote-api两个maven模块:

provider-module.png

2.2、添加spring boot、spring cloud依赖

在父模块provider中添加spring boot、spring cloud依赖
,spring cloud使用截止当前最新版本Hoxton.SR1,关联spring boot版本2.2.2.RELEASE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

注意:spring boot和spring cloud之间有版本依赖关系,如果想用其他版本,请自行查询对应的依赖版本,否则可能由于不兼容服务起不来

2.3、provider-service-remote-api模块编写feign接口

maven模块provider-service-remote-api引入spring cloud feign

1
2
3
4
5
6
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>

代码编写,新建IProviderRemoteService接口

1
2
3
4
5
6
@FeignClient(name = "provider-service")
public interface IProviderRemoteService {
@RequestMapping(value = "hello", method = RequestMethod.GET)
String hello();
}

2.4、provider-service模块编写接口实现

maven依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
<dependency>
<groupId>com.example</groupId>
<artifactId>provider-service-remote-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

接口实现类ProviderRemoteService

1
2
3
4
5
6
7
8
@RestController
public class ProviderRemoteService implements IProviderRemoteService {
@Override
public String hello() {
return "hello world!";
}
}

2.5、集成spring cloud consul

引入spring cloud consul模块

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>

application.yml添加consul配置

1
2
3
4
5
6
7
8
9
10
11
12
server:
port: 8080
spring:
application:
name: provider-service
cloud:
consul:
host: 127.0.0.1
port: 8500
discovery:
heartbeat:
enabled: true

启动类添加@EnableDiscoveryClient注解,启用服务发现功能

1
2
3
4
5
6
7
8
9
@SpringBootApplication
@EnableDiscoveryClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

到此,provider-service服务已经全部搭建完毕,完整项目结构:

provider-service.png

3、搭建consumer-service服务

3.1、创建maven模块

创建consumer项目,添加consumer-service,因为该服务不需要对外提供接口,所以无需consumer-service-remote-api模块:
consumer-module.png

3.2、consumer-service编写接口调用provider-service服务

引用provider-service-remote-api

1
2
3
4
5
<dependency>
<groupId>com.example</groupId>
<artifactId>provider-service-remote-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>

编写测试接口,通过feign调用provider-service服务

1
2
3
4
5
6
7
8
9
10
11
@RestController
public class ConsumerController {
@Autowired
private IProviderRemoteService providerRemoteService;
@RequestMapping(value = "/test")
public String test() {
return providerRemoteService.hello();
}
}

3.3、集成spring cloud consul

同provider-service服务一样,引入spring cloud consul模块

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>

application.yml添加consul配置

1
2
3
4
5
6
7
8
9
10
11
12
server:
port: 9090
spring:
application:
name: consumer-service
cloud:
consul:
host: 127.0.0.1
port: 8500
discovery:
heartbeat:
enabled: true

启动类添加@EnableDiscoveryClient注解,启用服务发现功能,并添加@EnableFeignClients注解,启用feign功能

1
2
3
4
5
6
7
8
9
10
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

到此,consumer-service服务也搭建完成,完整项目结构:

consumer-service.png

4、测试

4.1、启动consul服务

为了便于测试,笔者在本机以开发者模式起了一个consul服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
D:\consul>consul agent -dev
==> Starting Consul agent...
Version: 'v1.7.0'
Node ID: 'c43eedeb-f211-dbf2-e3fa-3caa64f86ddb'
Node name: 'DESKTOP-77V3R9P'
Datacenter: 'dc1' (Segment: '<all>')
Server: true (Bootstrap: false)
Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: 8502, DNS: 8600)
Cluster Addr: 127.0.0.1 (LAN: 8301, WAN: 8302)
Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false, Auto-Encrypt-TLS: false
==> Log data will now stream in as it occurs:
2020-02-22T15:34:07.878+0800 [DEBUG] agent: Using random ID as node ID: id=c43eedeb-f211-dbf2-e3fa-3caa64f86ddb
2020-02-22T15:34:07.900+0800 [DEBUG] agent.tlsutil: Update: version=1
2020-02-22T15:34:07.914+0800 [DEBUG] agent.tlsutil: OutgoingRPCWrapper: version=1
2020-02-22T15:34:07.916+0800 [INFO] agent.server.raft: initial configuration: index=1 servers="[{Suffrage:Voter ID:c43eedeb-f211-dbf2-e3fa-3caa64f86ddb Address:127.0.0.1:8300}]"
2020-02-22T15:34:07.916+0800 [INFO] agent.server.raft: entering follower state: follower="Node at 127.0.0.1:8300 [Follower]" leader=
2020-02-22T15:34:07.919+0800 [INFO] agent.server.serf.wan: serf: EventMemberJoin: DESKTOP-77V3R9P.dc1 127.0.0.1
2020-02-22T15:34:07.920+0800 [INFO] agent.server.serf.lan: serf: EventMemberJoin: DESKTOP-77V3R9P 127.0.0.1
2020-02-22T15:34:07.920+0800 [INFO] agent.server: Adding LAN server: server="DESKTOP-77V3R9P (Addr: tcp/127.0.0.1:8300) (DC: dc1)"
2020-02-22T15:34:07.921+0800 [INFO] agent.server: Handled event for server in area: event=member-join server=DESKTOP-77V3R9P.dc1 area=wan
2020-02-22T15:34:07.921+0800 [INFO] agent: Started DNS server: address=127.0.0.1:8600 network=udp
2020-02-22T15:34:07.923+0800 [INFO] agent: Started DNS server: address=127.0.0.1:8600 network=tcp
2020-02-22T15:34:07.926+0800 [INFO] agent: Started HTTP server: address=127.0.0.1:8500 network=tcp
2020-02-22T15:34:07.928+0800 [INFO] agent: started state syncer
==> Consul agent running!
...

4.2、启动服务注册到consul

分别启动provider-service服务和consumer-service服务,访问consul的Web UI界面可以看到两个服务都注册上来了:

consul-services.png

consul-nodes.png

4.3、调用测试接口

调用consumer-service测试接口http://127.0.0.1:9090/test

invoke.png

现在尝试把provider服务停止,consul注册中心可以看到健康检查状态为Critical,服务已经下线

`critical.png

此时,再次调用consumer-service测试接口,会报找不到服务

service not found.ong

5、Spring Cloud Consul应用配置

Name Default Description
spring.cloud.consul.config.acl-token
spring.cloud.consul.config.data-key data If format is Format.PROPERTIES or Format.YAML then the following field is used as key to look up consul for configuration.
spring.cloud.consul.config.default-context application
spring.cloud.consul.config.enabled TRUE
spring.cloud.consul.config.fail-fast TRUE Throw exceptions during config lookup if true, otherwise, log warnings.
spring.cloud.consul.config.format
spring.cloud.consul.config.name Alternative to spring.application.name to use in looking up values in consul KV.
spring.cloud.consul.config.prefix config
spring.cloud.consul.config.profile-separator ,
spring.cloud.consul.config.watch.delay 1000 The value of the fixed delay for the watch in millis. Defaults to 1000.
spring.cloud.consul.config.watch.enabled TRUE If the watch is enabled. Defaults to true.
spring.cloud.consul.config.watch.wait-time 55 The number of seconds to wait (or block) for watch query, defaults to 55. Needs to be less than default ConsulClient (defaults to 60). To increase ConsulClient timeout create a ConsulClient bean with a custom ConsulRawClient with a custom HttpClient.
spring.cloud.consul.discovery.acl-token
spring.cloud.consul.discovery.catalog-services-watch-delay 1000 The delay between calls to watch consul catalog in millis, default is 1000.
spring.cloud.consul.discovery.catalog-services-watch-timeout 2 The number of seconds to block while watching consul catalog, default is 2.
spring.cloud.consul.discovery.consistency-mode Consistency mode for health service request.
spring.cloud.consul.discovery.datacenters Map of serviceId’s → datacenter to query for in server list. This allows looking up services in another datacenters.
spring.cloud.consul.discovery.default-query-tag Tag to query for in service list if one is not listed in serverListQueryTags.
spring.cloud.consul.discovery.default-zone-metadata-name zone Service instance zone comes from metadata. This allows changing the metadata tag name.
spring.cloud.consul.discovery.deregister TRUE Disable automatic de-registration of service in consul.
spring.cloud.consul.discovery.enabled TRUE Is service discovery enabled?
spring.cloud.consul.discovery.fail-fast TRUE Throw exceptions during service registration if true, otherwise, log warnings (defaults to true).
spring.cloud.consul.discovery.health-check-critical-timeout Timeout to deregister services critical for longer than timeout (e.g. 30m). Requires consul version 7.x or higher.
spring.cloud.consul.discovery.health-check-headers Headers to be applied to the Health Check calls.
spring.cloud.consul.discovery.health-check-interval 10s How often to perform the health check (e.g. 10s), defaults to 10s.
spring.cloud.consul.discovery.health-check-path /actuator/health Alternate server path to invoke for health checking.
spring.cloud.consul.discovery.health-check-timeout Timeout for health check (e.g. 10s).
spring.cloud.consul.discovery.health-check-tls-skip-verify Skips certificate verification during service checks if true, otherwise runs certificate verification.
spring.cloud.consul.discovery.health-check-url Custom health check url to override default.
spring.cloud.consul.discovery.heartbeat.enabled FALSE
spring.cloud.consul.discovery.heartbeat.interval-ratio
spring.cloud.consul.discovery.heartbeat.ttl 30s
spring.cloud.consul.discovery.hostname Hostname to use when accessing server.
spring.cloud.consul.discovery.include-hostname-in-instance-id FALSE Whether hostname is included into the default instance id when registering service.
spring.cloud.consul.discovery.instance-group Service instance group.
spring.cloud.consul.discovery.instance-id Unique service instance id.
spring.cloud.consul.discovery.instance-zone Service instance zone.
spring.cloud.consul.discovery.ip-address IP address to use when accessing service (must also set preferIpAddress to use).
spring.cloud.consul.discovery.lifecycle.enabled TRUE
spring.cloud.consul.discovery.management-port Port to register the management service under (defaults to management port).
spring.cloud.consul.discovery.management-suffix management Suffix to use when registering management service.
spring.cloud.consul.discovery.management-tags Tags to use when registering management service.
spring.cloud.consul.discovery.order 0 Order of the discovery client used by?CompositeDiscoveryClient?for sorting available clients.
spring.cloud.consul.discovery.port Port to register the service under (defaults to listening port).
spring.cloud.consul.discovery.prefer-agent-address FALSE Source of how we will determine the address to use.
spring.cloud.consul.discovery.prefer-ip-address FALSE Use ip address rather than hostname during registration.
spring.cloud.consul.discovery.query-passing FALSE Add the ‘passing` parameter to /v1/health/service/serviceName. This pushes health check passing to the server.
spring.cloud.consul.discovery.register TRUE Register as a service in consul.
spring.cloud.consul.discovery.register-health-check TRUE Register health check in consul. Useful during development of a service.
spring.cloud.consul.discovery.scheme http Whether to register an http or https service.
spring.cloud.consul.discovery.server-list-query-tags Map of serviceId’s → tag to query for in server list. This allows filtering services by a single tag.
spring.cloud.consul.discovery.service-name Service name.
spring.cloud.consul.discovery.tags Tags to use when registering service.
spring.cloud.consul.enabled TRUE Is spring cloud consul enabled.
spring.cloud.consul.host localhost Consul agent hostname. Defaults to ‘localhost’.
spring.cloud.consul.port 8500 Consul agent port. Defaults to ‘8500’.
spring.cloud.consul.retry.initial-interval 1000 Initial retry interval in milliseconds.
spring.cloud.consul.retry.max-attempts 6 Maximum number of attempts.
spring.cloud.consul.retry.max-interval 2000 Maximum interval for backoff.
spring.cloud.consul.retry.multiplier 1.1 Multiplier for next interval.
spring.cloud.consul.scheme Consul agent scheme (HTTP/HTTPS). If there is no scheme in address - client will use HTTP.
spring.cloud.consul.tls.certificate-password Password to open the certificate.
spring.cloud.consul.tls.certificate-path File path to the certificate.
spring.cloud.consul.tls.key-store-instance-type Type of key framework to use.
spring.cloud.consul.tls.key-store-password Password to an external keystore.
spring.cloud.consul.tls.key-store-path Path to an external keystore.

详情参考官网:https://cloud.spring.io/spring-cloud-consul/reference/html/appendix.html